//============================================================================
// Name        : gspdc_grasp.cpp
// Author      :
// Version     :
// Copyright   : Your copyright notice
// Description : Main, Ansi-style
//============================================================================

#include <limits.h>


#include "graph.hh"
#include "construct_greedy_randomized_solution.hh"
#include "local_search_neighborhood_randomly.hh"
#include "local_search_key_path.hh"
#include "utilis.hh"


using namespace std;

int main(int argc, char *argv[]) {
	if(argc < 3) {
		cout << "[ERROR][main]: Invalid arguments" << endl;
		cout << "[INFO][main]: ./gspdc_grasp <topology_path_file_in> <topology_path_file_out>" << endl;
		return -1;
	}

	// initialize random seed
	srand(time(NULL));

	//// Parameters Settings ////
	int k = 10; // an integer more than 1
	int max_iter = 2000; // an integer more than 1
	double beta = 0.01; // an double between (0, 1)
	double alpha = 0.01; // an double between (0, 1)
	int size_pool = 10; // an integer more than 1


	char * path_file_in = argv[1]; // load from argv[]
	char * path_file_out = argv[2]; // load from argv[]
	pair<Graph*, PathMatrix*> * G_P;

	cout << "[INFO][main]: Init(...)" << endl;
	Graph * Problem = new Graph(path_file_in);

	Graph * G_best = new Graph();
	PathMatrix * PM_G_best = new PathMatrix();
	int G_best_cost = INT_MAX;

	for (int i = 0; i < max_iter; i++) {
		cout << "[INFO][main]: Iteration: " << i+1 << endl;

		G_P = ConstructGreedyRandomizedSolution(Problem, k);

		if(G_P) { // Si es una solucion factible
RETRY:
			LocalSearchNeighborhoodRandomly(Problem, k, G_P->first, G_P->second, alpha, beta, size_pool);
			if (G_P->first->Cost() < G_best_cost) {
				delete G_best;
				delete PM_G_best;

				G_best = new Graph(G_P->first);
				G_best_cost = G_P->first->Cost();
				PM_G_best = new PathMatrix(G_P->second);
			}

			LocalSearchKeyPath(Problem, G_P->first, G_P->second);
			if (G_P->first->Cost() < G_best_cost) {
				delete G_best;
				delete PM_G_best;

				G_best = new Graph(G_P->first);
				G_best_cost = G_P->first->Cost();
				PM_G_best = new PathMatrix(G_P->second);
				goto RETRY;
			}

			DeletePair(G_P);
		}
	}

	G_best->Dump(path_file_out);

	delete PM_G_best;
	delete G_best;
	delete Problem;

	cout << "[INFO][main]: End(...)" << endl;
	return 0;
}
